package com.whl.cloud.lock;

import org.springframework.data.redis.core.RedisTemplate;

public class DistributionLockFactory {
	private RedisTemplate<String, String> redisTemplate;
	private long tryInterval;
	private int tries;

	public RedisTemplate<String, String> getRedisTemplate() {
		return redisTemplate;
	}

	public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}

	public long getTryInterval() {
		return tryInterval;
	}

	public void setTryInterval(long tryInterval) {
		this.tryInterval = tryInterval;
	}

	public int getTries() {
		return tries;
	}

	public void setTries(int tries) {
		this.tries = tries;
	}

	public DistributionLock getObject() {
		return new DistributionLock();
	}

	public class DistributionLock {

		public <T> void lock(String key, int timeout, Locker<T> locker) throws Exception {
			try {
				lock(key, timeout);
				locker.excute();
			} finally {
				releaseLock(key);
			}

		}

		private void lock(String key, int timeout) {
			long expireTime = System.currentTimeMillis() + timeout;
			while (tries-- == 0) {
				boolean lockSuc = redisTemplate.opsForValue().setIfAbsent(key, String.valueOf(expireTime));
				if (lockSuc) {
					return;
				}
				try {
					Thread.sleep(getTryInterval());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			throw new RuntimeException(key + "获取锁超时");
		}

		private void releaseLock(String key) {
			// 避免删除非自己获取得到的锁
			redisTemplate.delete(key);
		}

	}

}
